import is from './is.js'

const read = {
  number: (input) => {
    let hasDot = false
    const number = read.while(input, (ch) => {
      if (ch === '.') {
        if (hasDot) {
          return false
        }
        hasDot = true
        return true
      }
      return is.digit(ch)
    })
    return {
      type: 'number',
      value: parseFloat(number)
    }
  },
  identifier: (input) => {
    const id = read.while(input, is.id)
    return {
      type: is.keyword(id) ? 'keyword' : 'identifier',
      value: id
    }
  },
  literal: (input) => {
    return {
      type: 'literal',
      value: read.escaped(input, '"')
    }
  },
  punctuation: (input) => {
    return {
      type: 'punctuation',
      value: input.next()
    }
  },
  operator: (input) => {
    return {
      type: 'operator',
      value: read.while(input, is.operator)
    }
  },
  dot: (input) => {
    return {
      type: 'dot',
      value: input.next()
    }
  },
  escaped: (input, end) => {
    let escaped = false
    let str = ''
    input.next()
    while (!input.eof()) {
      const ch = input.next()
      if (escaped) {
        if (ch === 't') {
          str += '\t'
        } else if (ch === 'n') {
          str += '\n'
        } else {
          str += ch
        }
        escaped = false
      } else if (ch === '\\') {
        escaped = true
      } else if (ch === end) {
        break
      } else {
        str += ch
      }
    }
    return str
  },
  comment: (input) => {
    read.while(input, (ch) => {
      return ch !== '\n'
    })
    input.next()
  },
  while: (input, predicate) => {
    let str = ''
    while (!input.eof() && predicate(input.peek())) {
      str += input.next()
    }
    return str
  }
}

export default read
